﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

//Author: ljj yjc
//Date: 20190613
//Funciont: 控制玩家所操控的角色

//TODO:  1.改成碰撞盒的形式
public class Player : MonoBehaviour
{
    public static Player Instance
    {
        get
        {
            if (_Instance == null)
            {
                _Instance = GameObject.FindObjectOfType<Player>();
            }
            if (!_Instance)
            {
                GameObject obj = new GameObject("Player");
                _Instance = obj.AddComponent<Player>();
            }
            return _Instance;
        }
        set
        {
            _Instance = value;
        }
    }
    private static Player _Instance;

    public Transform trans;
    public float speed = 5.0f;
    public float attack = 1.0f;
    private Vector3 targetPos;
    private float waveTime = 0f;
    Vector3 originPos = new Vector3(0.0f, 0.0f, 0.0f);
    BattleObject battle;
    Animator animator;
    bool isWalking;
    BoxCollider2D coll;
    
    //技能:无敌斩
    GameObject prefab;
    List<GameObject> targets;
    Collider2D[] temps;
    public int OmnislashRange = 5;
    public int OmnislashCD = 3;
    private int currentCD = 0;

    public float GetHP()
    {
        return gameObject.GetComponent<HitPoint>().getCurrentHP();
    }

    public float GetMaxHP()
    {
        return gameObject.GetComponent<HitPoint>().getMaxHP();
    }

    private void Awake()
    {
        prefab = Resources.Load("Prefabs/Omnislash") as GameObject;
    }
    // Start is called before the first frame update
    void Start()
    {
        trans = this.GetComponent<Transform>();
        coll = this.GetComponent<BoxCollider2D>();
        Vector3 playerPos;
        isWalking = false;
        animator = gameObject.GetComponentInChildren<Animator>();
        battle = gameObject.GetComponent<BattleObject>();
        if (ConstOfMap.loadgame)
        {
            playerPos = new Vector3(ConstOfMap.save.playerPos.x, ConstOfMap.save.playerPos.y, 0f);
            battle.setMaxHP(ConstOfMap.save.JOJOMaxhp);
            battle.setHP(ConstOfMap.save.JOJOhp);
            StreamWriter sw1 = new StreamWriter(Application.dataPath + "/Save/test1.json");
            sw1.Write(battle.getHP()+"/"+ battle.getMaxHP());
            sw1.Close();
            battle.SetAllBuff(ConstOfMap.save.JOJObuff);
        }
        else playerPos = Function.LogicPosToWorldPos(ConstOfMap.initPlayerPos);
        playerPos.z = playerPos.y * 0.1f;
        trans.position = playerPos;
        targetPos = trans.position;
        ViewController.Instance.SetPlayerPos(trans.position);//让镜头初始跟随玩家
    }

    // Update is called once per frame
    void Update()
    {
        if (waveTime > 0f)
        {
            waveTime -= Time.deltaTime;
            if (waveTime > 0.2f)
            {
                animator.SetInteger("State", 2);
            }
            else if (waveTime > 0f)
            {
                animator.SetInteger("State", 3);
            }
            else
                animator.SetInteger("State", 0);
        }
        if (Tag.playerPause)
            return;

        if (!battle.CanWalk())
            return;

        if (Input.GetKeyDown(KeyCode.Q))
        {
            battle.PlayerActiveAttack();
        }
        /*
        if(Input.GetKeyDown(KeyCode.Q))
        {
            if(APController.Instance.wave>=currentCD)
            {
                currentCD = APController.Instance.wave + OmnislashCD;
                StartCoroutine(Omnislash());
            }
            else
            {
                MessageController.Instance.SendMsg("无敌斩冷却:" + (currentCD - APController.Instance.wave)+"波");
            }
            
        }
        */
        float len = Time.deltaTime * speed * ConstOfMap.xGap;
        Vector3 targetForward = Vector3.zero;
        int inputU = Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow) ? 1 : 0;
        int inputD = Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow) ? 1 : 0;
        int inputL = Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow) ? 1 : 0;
        int inputR = Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow) ? 1 : 0;

        targetForward.x = (inputR - inputL);
        targetForward.y = (inputU - inputD);
        Vector2 direct = targetForward;

        if (direct == Vector2.zero)
        {
            UpdateWalkParam(false);
            return;
        }

        targetForward = targetForward * len / Function.DistanceIgnoreZ(targetForward, Vector3.zero);
        Vector3 nowWorldPos = trans.position;
        Vector3 targetWorldPos = nowWorldPos + targetForward;

        bool hasHit = false;
        for (int i = -1; i <= 1; i += 2)
        {
            for (int j = -1; j <= 1; j += 2)
            {
                if (targetForward.x * i <= 0 && targetForward.y * j <= 0)
                    continue;
                Vector3 offset = new Vector3(i * coll.size.x * 0.65f, j * coll.size.y * 0.65f, 0);
                RaycastHit2D hit = Physics2D.Linecast(nowWorldPos + offset, targetWorldPos + offset, LayerMask.GetMask("Cube", "Tower", "Magma"));
                if (hit.point != Vector2.zero)
                {
                    hasHit = true;
                    Vector3 hitPointForward = new Vector3(hit.point.x, hit.point.y, 0) - (nowWorldPos + offset);
                    float hitPointDistance = Function.LengthIgnoreZ(hitPointForward);
                    if (hitPointDistance < Function.LengthIgnoreZ(targetForward))
                    {
                        targetForward = hitPointForward;
                    }
                }
            }
        }

        if (hasHit) targetForward *= 0.9f;

        //移动
        float length = Function.LengthIgnoreZ(targetForward);

        if (length < 0.001f)
        {
            SetSight(direct, nowWorldPos);
            return;
        }
            

        //减少行动力
        if (length > 0 && !APController.Instance.TryDecreaseAPForWalk())
        {
            SetSight(direct, nowWorldPos);
            return;
        }

        nowWorldPos += targetForward;
        SetSight(direct, nowWorldPos);
        UpdateWalkParam(Function.DistanceIgnoreZ(targetForward, Vector3.zero) > 0.001f);
        if (Mathf.Abs(targetForward.x) > 0.001f)
            battle.UpdateMirrorParam(targetForward.x < 0);
        trans.position = new Vector3(nowWorldPos.x, nowWorldPos.y, nowWorldPos.y * 0.1f);
        MapManager.Instance.SetPlayerPos(Function.WorldPosToLogicPos(nowWorldPos.x, nowWorldPos.y));
        if(Mathf.Abs(targetForward.x) > 0.001f || Mathf.Abs(targetForward.y) > 0.001f)
        {
            ViewController.Instance.SetPlayerPos(trans.position);
        }

        
    }

    void UpdateWalkParam(bool isWalking)
    {
        if (this.isWalking != isWalking)
        {
            this.isWalking = isWalking;
            animator.SetBool("Walk", isWalking);
        }
    }

    public void waveAction(Vector3 pos)
    {
        battle.UpdateMirrorParam((pos - transform.position).x < 0);
        waveTime = 0.4f;
    }

    void SetSight(Vector2 direct, Vector2 nowWorldPos)
    {
        if (Tag.mouseDelay > ConstOfMap.MOUSEUNMOVE && !Tag.playerPause)
        {
            //Debug.Log(targetForward.ToString() + "   " + nowWorldPos.ToString());
            //MouseController.Instance.SetSightPosition(nowWorldPos.x + targetForward.x * (ConstOfMap.xGap + playerWidth / 2), nowWorldPos.y + targetForward.y * (ConstOfMap.yGap + playerHeight / 2));
            MouseController.Instance.SetSightPosition(nowWorldPos.x + direct.x * (ConstOfMap.xGap + coll.size.x * 0.5f + coll.offset.x), nowWorldPos.y + direct.y * (ConstOfMap.yGap + coll.size.y * 0.5f + coll.offset.y));
        }
    }


    bool Invalid(Vector2 pos)
    {
        return (!MapManager.Instance.IsPassable(Function.WorldPosToLogicPos(pos))); 
    }

    public Vector2 GetPlayerPos()
    {
        return trans.position;
    }

    private IEnumerator Omnislash()
    {
        temps = Physics2D.OverlapCircleAll(gameObject.transform.position, OmnislashRange* ConstOfMap.xGap, Function.GetTargetLayerMask(Identity.aibo));
        foreach (Collider2D target in temps)
        {
            if(target != null)
            {
                EffectObjectManager.Instance.CreateEffectObject(prefab, target.transform.position, Quaternion.Euler(0, 0, RandomGenerator.Instance.Next(-45, 45)), target.transform);
                yield return new WaitForSeconds(0.1f);
            }          
        }
        //Omnislash
    }

    public List<BuffInfo> GetBuff()
    {
        return gameObject.GetComponent<BattleObject>().GetAllBuff();
    }

    public void Heal(float hp = 0.1f)
    {
        gameObject.GetComponent<HitPoint>().healHP(hp);
    }
}
